package org.qdao.util;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;
import java.lang.reflect.InvocationTargetException;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.qdao.DBConfig;
import org.qdao.DBEngineFactory;
import org.qdao.IDBEngine;
import org.qdao.IEntityDao;

public class DBEngineUtil {
	private static final String line = System.getProperty("line.separator");
	private static final StringBuilder databaseMeta = new StringBuilder(50);

	/**
	 * 
	 * @author tan
	 * @param clazz
	 * @return
	 * @throws IllegalArgumentException
	 * @throws SecurityException
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 * @throws InvocationTargetException
	 * @throws NoSuchMethodException
	 * @throws ClassNotFoundException
	 * @throws SQLException
	 *             2010/03/03 12:05:19
	 */
	public static IEntityDao<?> getEntityDao(Class<?> clazz) throws IllegalArgumentException, SecurityException, InstantiationException, IllegalAccessException, InvocationTargetException,
			NoSuchMethodException, ClassNotFoundException, SQLException {
		return initializeDBEngine().getEntityDao(clazz, true);
	}

	/**
	 * 
	 * @author tan
	 * @param clazz
	 * @param isLogger
	 * @return
	 * @throws IllegalArgumentException
	 * @throws SecurityException
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 * @throws InvocationTargetException
	 * @throws NoSuchMethodException
	 * @throws ClassNotFoundException
	 * @throws SQLException
	 *             2010/03/03 12:05:24
	 */
	public static IEntityDao<?> getEntityDao(Class<?> clazz, boolean isLogger) throws IllegalArgumentException, SecurityException, InstantiationException, IllegalAccessException,
			InvocationTargetException,
			NoSuchMethodException, ClassNotFoundException, SQLException {
		return initializeDBEngine().getEntityDao(clazz, isLogger);
	}

	public static IEntityDao<?> getEntityDao(DBConfig config, Class<?> clazz, boolean isLogger) throws IllegalArgumentException, SecurityException, InstantiationException, IllegalAccessException,
			InvocationTargetException,
			NoSuchMethodException, ClassNotFoundException, SQLException {
		return initializeDBEngine(config).getEntityDao(clazz, isLogger);
	}

	public static IDBEngine initializeDBEngine()  {
		DBConfig config = DBConfig.getInstance();
		// config.driver = "oracle.jdbc.driver.OracleDriver";
		// System.out.println(config.driver.indexOf("oracle"));
		// config.username = "QDAO";
		// config.password = "QDAO";
		// config.url = "jdbc:oracle:thin:@WAMNET-SVR:1521:WAMNET";
		// config.jarPath = new String[] { "D:\\JAR\\ojdbc6.jar" };

//		config.driver = "com.mysql.jdbc.Driver";
//		config.username = "root";
//		config.password = "tanyuanji";
//		config.url = "jdbc:mysql://localhost:3306/qdao";
//		config.jarPath = new String[] { "D:\\librarys\\mysql-connector-java-5.1.11-bin.jar" };

		// config.driver = "oracle.jdbc.driver.OracleDriver";
		// System.out.println(config.driver.indexOf("oracle"));
		// config.username = "QDAO";
		// config.password = "QDAO";
		// config.url = "jdbc:oracle:thin:@WAMNET-SVR:1521:WAMNET";
		// config.jarPath = new String[] { "D:\\JAR\\ojdbc6.jar" };

		// initialize the engine
		IDBEngine engine = DBEngineFactory.getEngine(config);
		try
        {
            engine.initialize(config);
        }
        catch (InstantiationException e)
        {
            e.printStackTrace();
        }
        catch (IllegalAccessException e)
        {
            e.printStackTrace();
        }
        catch (ClassNotFoundException e)
        {
            e.printStackTrace();
        }
        catch (SQLException e)
        {
            e.printStackTrace();
        }
		return engine;
	}

	/**
	 * <pre>
	 * driver = &quot;oracle.jdbc.driver.OracleDriver&quot;;
	 * 
	 * username = &quot;QDAO&quot;;
	 * 
	 * password = &quot;QDAO&quot;;
	 * 
	 * url = &quot;jdbc:oracle:thin:@WAMNET-SVR:1521:WAMNET&quot;;
	 * 
	 * jarPaths = new String[] { "D:\\JAR\\ojdbc6.jar" };
	 * 
	 * <pre>
	 * @author tan
	 * @param jarPaths
	 * @param driver
	 * @param url
	 * @param username
	 * @param password
	 * @return
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 * @throws ClassNotFoundException
	 * @throws SQLException
	 * 2010/03/03 11:59:41
	 */
	public static IDBEngine initializeDBEngine(String[] jarPaths, String driver, String url, String username, String password) throws InstantiationException, IllegalAccessException,
			ClassNotFoundException,
			SQLException {
		DBConfig config = DBConfig.getInstance();
		config.driver = driver;
		config.username = username;
		config.password = password;
		config.url = url;
		config.jarPath = jarPaths;

		// initialize the engine
		IDBEngine engine = DBEngineFactory.getEngine(config);
		engine.initialize(config);
		return engine;
	}

	/**
	 * 
	 * @author tan
	 * @param config
	 * @return
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 * @throws ClassNotFoundException
	 * @throws SQLException
	 *             2010/03/03 12:06:40
	 */
	public static IDBEngine initializeDBEngine(DBConfig config) throws InstantiationException, IllegalAccessException,
			ClassNotFoundException,
			SQLException {
		// initialize the engine
		IDBEngine engine = DBEngineFactory.getEngine(config);
		engine.initialize(config);
		return engine;
	}
	


	public static void exportDatabaseInformation(IDBEngine engine, String path) {
		try {
			getDatabaseInformation(engine);
		} catch (SQLException e1) {
			e1.printStackTrace();
		} catch (InstantiationException e1) {
			e1.printStackTrace();
		} catch (IllegalAccessException e1) {
			e1.printStackTrace();
		} catch (ClassNotFoundException e1) {
			e1.printStackTrace();
		}
		File file = new File(path);
		if (file.isDirectory() || file.exists()) {
			file.delete();
			try {
				file.createNewFile();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		Writer writer = null;
		try {
			writer = new FileWriter(path);
			writer.write(databaseMeta.toString());
			writer.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		println(path + " write success!");
	}

	public static void exportDatabaseInformation(String path, String charset) {
		try {
			getDatabaseInformation(initializeDBEngine());
		} catch (SQLException e1) {
			e1.printStackTrace();
		} catch (InstantiationException e1) {
			e1.printStackTrace();
		} catch (IllegalAccessException e1) {
			e1.printStackTrace();
		} catch (ClassNotFoundException e1) {
			e1.printStackTrace();
		}
		File file = new File(path);
		if (file.isDirectory() || file.exists()) {
			file.delete();
			try {
				file.createNewFile();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		OutputStream out = null;
		try {
			out = new BufferedOutputStream(new FileOutputStream(file));
			byte[] buf = databaseMeta.toString().getBytes(charset);
			out.write(buf, 0, buf.length);
			if (out != null) {
				out.close();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public static void exportDatabaseInformation(IDBEngine engine, String path, String charset) {
		try {
			getDatabaseInformation(engine);
		} catch (SQLException e1) {
			e1.printStackTrace();
		} catch (InstantiationException e1) {
			e1.printStackTrace();
		} catch (IllegalAccessException e1) {
			e1.printStackTrace();
		} catch (ClassNotFoundException e1) {
			e1.printStackTrace();
		}
		File file = new File(path);
		if (file.isDirectory() || file.exists()) {
			file.delete();
			try {
				file.createNewFile();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		OutputStream out = null;
		try {
			out = new BufferedOutputStream(new FileOutputStream(file));
			byte[] buf = databaseMeta.toString().getBytes(charset);
			out.write(buf, 0, buf.length);
			if (out != null) {
				out.close();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private static void processByJDBC(IDBEngine engine) throws SQLException, InstantiationException, IllegalAccessException, ClassNotFoundException {
		// get the connection
		Connection conn = engine.getConnection();

		// operate the jdbc
		PreparedStatement pstmt = conn.prepareStatement("select * from CAT");
		ResultSet rs = pstmt.executeQuery();
		while (rs.next()) {
			System.out.println(rs.getString(1));

		}

		// if (conn != null) {
		// System.out.println("connection is right");
		// }

		// dispose the resource
		engine.dispose();
		pstmt.close();
		// System.out.println("connection is dispose");
	}

	private static String getDatabaseInformation(IDBEngine engine) throws SQLException, InstantiationException, IllegalAccessException, ClassNotFoundException {
		if (!isEmpty(databaseMeta)) {
			return "";
		}
		// get the connection
		Connection conn = engine.getConnection();
		DatabaseMetaData meta = conn.getMetaData();
		// String Buffer to append the information of the database
		StringBuilder information = new StringBuilder();
		databaseMeta
				.append("数据库产品的名称:")
				.append(meta.getDatabaseProductName()).append(line)
				.append("数据库的产品版本号:")
				.append(meta.getDatabaseProductVersion()).append(line)
				.append("底层数据库的主版本号:")
				.append(meta.getDatabaseMajorVersion()).append(line)
				.append("底层数据库的次版本号:")
				.append(meta.getDatabaseMinorVersion()).append(line)
				.append("JDBC 驱动程序的名称:")
				.append(meta.getDriverName()).append(line)
				.append("JDBC 驱动版本号:")
				.append(meta.getDriverVersion()).append(line)
				.append("JDBC 驱动程序的主版本号:")
				.append(meta.getDriverMajorVersion()).append(line)
				.append("JDBC 驱动程序的次版本号:")
				.append(meta.getDriverMinorVersion()).append(line)
				.append("主 JDBC 版本号:")
				.append(meta.getJDBCMajorVersion()).append(line)
				.append("次 JDBC 版本号:")
				.append(meta.getJDBCMinorVersion()).append(line)
				.append("数据库允许内嵌二进制字面值中使用的最大十六进制字符数:")
				.append(meta.getMaxBinaryLiteralLength()).append(line)
				.append("数据库允许用于类别名称的最大字符数:")
				.append(meta.getMaxCatalogNameLength()).append(line)
				.append("数据库允许用于字符字面值的最大字符数:")
				.append(meta.getMaxCharLiteralLength()).append(line)
				.append("数据库允许用于列名称的最大字符数:")
				.append(meta.getMaxColumnNameLength()).append(line)
				.append("数据库允许在 GROUP BY 子句中使用的最大列数:")
				.append(meta.getMaxColumnsInGroupBy()).append(line)
				.append("数据库允许在 ORDER BY 子句中使用的最大列数:")
				.append(meta.getMaxColumnsInOrderBy()).append(line)
				.append("数据库允许在SELECT 列表中使用的最大列数:")
				.append(meta.getMaxColumnsInSelect()).append(line)
				.append("数据库允许在表中使用的最大列数:")
				.append(meta.getMaxColumnsInTable()).append(line)
				.append("数据库允许连接到此数据库并发连接可能最大的列数:")
				.append(meta.getMaxConnections()).append(line)
				.append("数据库中允许用于游标名称的最大字符数:")
				.append(meta.getMaxCursorNameLength()).append(line)
				.append("数据库允许用于索引(包括索引的所有的部分)的最大字节数:")
				.append(meta.getMaxIndexLength()).append(line)
				.append("数据库允许在索引中使用的最大列数:")
				.append(meta.getMaxColumnsInIndex()).append(line)
				.append("数据库允许用于过程名称的最大字符数:")
				.append(meta.getMaxProcedureNameLength()).append(line)
				.append("数据库允许单行中使用的最大字节数:")
				.append(meta.getMaxRowSize()).append(line)
				.append("数据库允许模式名称中使用的最大字符数:")
				.append(meta.getMaxSchemaNameLength()).append(line)
				.append("SQL语句中使用的最大字符数:")
				.append(meta.getMaxStatementLength()).append(line)
				.append("数据库中同一时间内可处于开放状态最大活动语句数:")
				.append(meta.getMaxStatements()).append(line)
				.append("表名称使用最大字符数:")
				.append(meta.getMaxTableNameLength()).append(line)
				.append(" SELECT 语句中使用的表的最大数量:")
				.append(meta.getMaxTablesInSelect()).append(line)
				.append("用户名称最大字符数:")
				.append(meta.getMaxUserNameLength()).append(line)
				.append("数据库已知的用户名:")
				.append(meta.getUserName()).append(line)
				.append("数据库是否处于只读模式:")
				.append(meta.isReadOnly()).append(line)
				.append("默认的事务的隔离级别:")
				.append(meta.getDefaultTransactionIsolation()).append(line);
		// println(databaseMeta.toString());
		engine.dispose();
		conn.close();
		return information.toString();
	}

	private static void println(String string) {
		System.out.println(string);
	}

	public static boolean isEmpty(CharSequence string) {
		return string == null || string.toString().trim().length() == 0;
	}

	public static void exportDatabaseInformation(String path) {
		try {
			getDatabaseInformation(initializeDBEngine());
		} catch (SQLException e1) {
			e1.printStackTrace();
		} catch (InstantiationException e1) {
			e1.printStackTrace();
		} catch (IllegalAccessException e1) {
			e1.printStackTrace();
		} catch (ClassNotFoundException e1) {
			e1.printStackTrace();
		}
		File file = new File(path);
		if (file.isDirectory() || file.exists()) {
			file.delete();
			try {
				file.createNewFile();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		Writer writer = null;
		try {
			writer = new FileWriter(path);
			writer.write(databaseMeta.toString());
			writer.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		println(path + " write success!");
	}
}
